%% coding: utf-8
-module(birthday).
-compile(export_all).

% 逻辑谜题
% 一个推测生日的程序
% 用于说明函数式编程的特点：更多地去思考如何定义问题，而不是解决问题
% 或者说，通过定义问题的方式去解决问题，和prolog, lisp语言很像
% 问题定义清楚了(是啥，如何定义)，问题也就解决了

dates() ->
    [
        {may,15},{may,16},{may,19},
        {june,17},{june,18},
        {july,14},{july,16},
        {augest,14},{augest,15},{augest,17}
    ].

% 列表过滤
tell({month,Month}, PossibleDates) ->
    [Date || Date = {M,_} <- PossibleDates, M =:= Month];
tell({day,Day}, PossibleDates) ->
    [Date || Date = {_,D} <- PossibleDates, D =:= Day].

know([_One]) -> true;
know(_PossibleDates) -> false.

month({Month,_}) -> {month, Month}.
day({_,Day}) -> {day, Day}.

statements3(Date) ->
    PossibleDates = tell(month(Date), dates()),
    not know(PossibleDates)
    andalso
    lists:all(fun(I) -> I end, [not know(tell(day(D),dates())) || D <- PossibleDates]).

statements4(Date) ->
    AtFirst = tell(day(Date), dates()),
    not know(AtFirst)
    andalso
    % 要使用第三个论断
    know(lists:filter(fun statements3/1, AtFirst)).

statements5(Date) ->
    PossibleDates = tell(month(Date), dates()),
    know(lists:filter(fun statements4/1, PossibleDates)).

statements3to5(Date) ->
    statements3(Date) andalso
    statements4(Date) andalso
    statements5(Date).

chery_birthday() -> lists:filter(fun statements3to5/1, dates()).
